
                /*********************************************
                **                                          **
                **                                          **
                **           bcast_rows_in_array            **
                **                                          **
                **                                          **
                *********************************************/
                /*********************************************
                **                                          **
                **         Author Jean-Marc Adamo           **
                **       Copyright (C) 1997-2008 JMA        **
                *********************************************/


/*
** execute with n**2 processes
*/


#include "arch.h"
#include "math.h"
#include "A.utilities"

//user program

Coll_id cid[10];

//on most homogenous systems, explicit setting
//wont be necessary (try commenting the
//setting lines, you should get the same values
//for cid).
void init(int, char **){
   int sqrt_pn = (int)sqrt((double)Sdf::PROC_NB);
   for(int i  = 0; i < sqrt_pn; i++){
      cid[i].set();
      fprintf(Sdf::trace, "node%d: cid[%d]=%d\n",
              Sdf::PROC_ID, i, cid[i].get());
   }
   fflush(Sdf::trace);
}

class Root_proc: public Thread{

   public:

        int     sqrt_pn;
        int    *rank;
        Group **group;
        CommL **comml;

        Root_proc()
                : Thread((Tmf0_ptr)&Root_proc::body){}

        void body(){

                fprintf(Sdf::trace, "node %d, in Root_proc::body1\n", Sdf::PROC_ID);
                fflush(Sdf::trace);

                double d_sqrt_pn = sqrt((double)Sdf::PROC_NB);
                int sqrt_pn = (int)sqrt((double)Sdf::PROC_NB);
                if((double)sqrt_pn*(double)sqrt_pn != d_sqrt_pn*d_sqrt_pn){
                   printf("*****ERROR: process number is not a square int\n");
                   fflush(stdout);
                   return;
                }

                rank = new int[Sdf::PROC_NB];
                int i;
                for(i  = 0; i < Sdf::PROC_NB; i++)
                   rank[i] = i;

                group = new Group*[sqrt_pn];
                comml = new CommL*[sqrt_pn];
                for(i = 0; i < sqrt_pn; i++){
                   group[i] = Sdf::incl(Sdf::COMML_WORLD, sqrt_pn, rank + i*sqrt_pn);

                   fprintf(Sdf::trace, "node %d, in Root_proc::body14 %d, %d, %d, %d, %d, %d, %d\n",
                           Sdf::PROC_ID,
                           i,
                           sqrt_pn,
                           (rank + i*sqrt_pn)[0],(rank + i*sqrt_pn)[1], (rank + i*sqrt_pn)[2],
                           rank + i*sqrt_pn,
                           &rank[i*sqrt_pn]);

                   comml[i] = group[i]->commit(cid[i], Sdf::COMML_WORLD);
                   //caution: commit creates a COMML object
                   //                transfers the group attributes to the object
                   //                applies delete the Group object
                   //         as a consequence, the group object which commit has
                   //         been applied to does not exit any longer, the pointer
                   //         in group[i] becomes inconsistent, so delete *mustn't* 
                   //         be applied to it.

                   fprintf(Sdf::trace, "node %d, in Root_proc::body15 %d\n",
                           Sdf::PROC_ID,
                           cid[i].get());
                }

                fflush(Sdf::trace);
                int h_index = Sdf::PROC_ID/sqrt_pn;
                int v_index = Sdf::PROC_ID%sqrt_pn;
                int g_root = h_index;

                fprintf(Sdf::trace, "node %d, in Root_proc::body16 %d, %d, %d\n",
                        Sdf::PROC_ID,
                        h_index, v_index, g_root);
                fflush(Sdf::trace);

                int to = (int)Sdf::PROC_ID;
                fprintf(Sdf::trace, "node %d, in Root_proc::body2, to = %d\n",
                        Sdf::PROC_ID, to);
                _Sdf<int>::bcast(to, 1, g_root, cid[h_index], comml[h_index]);
                fprintf(Sdf::trace, "node %d, in Root_proc::body3, to = %d\n",
                        Sdf::PROC_ID, to);
                fflush(Sdf::trace);

                for(i  = 0; i < sqrt_pn; i++){
                   delete comml[i];
                   //no delete group[i], see caution above.
                }

                delete []comml;
                delete []group;
                delete []rank;
                fprintf(Sdf::trace, "node %d, in Root_proc::body4\n", Sdf::PROC_ID);
        }
};
//end of user program

MAIN(Root_proc, init, Sdf::empty_f, Sdf::empty_e)
